﻿using LowCoding.Dto;
using SqlSugar;
using System.Linq.Expressions;

namespace LowCoding.Application
{
    public interface IServiceBase<TEntity, TEntityInput, TEntityOutput, TEntitySearch, TKey>
     where TEntityInput : class
     where TEntityOutput : class
     where TEntitySearch : class
     //where TEntityDetailDto : class
    {

        #region 根据条件查询记录

        /// <summary>
        /// 根据条件查询记录
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        List<TEntityOutput> GetList(TEntitySearch search);

        /// <summary>
        /// 根据条件查询记录
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        Task<List<TEntityOutput>> GetListAsync(TEntitySearch search);

        #endregion 根据条件查询记录

        #region 根据条件查询指定列返回记录

        /// <summary>
        /// 根据条件查询指定列返回记录
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="whereExpression"></param>
        /// <param name="selectcolumns"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        object GetColumnsList<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> selectcolumns, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);

        /// <summary>
        /// 根据条件查询指定列返回记录
        /// </summary>
        /// <typeparam name="TResult"></typeparam>
        /// <param name="whereExpression"></param>
        /// <param name="selectcolumns"></param>
        /// <param name="orderByExpression"></param>
        /// <param name="orderByType"></param>
        /// <returns></returns>
        Task<object> GetColumnsListAsync<TResult>(Expression<Func<TEntity, bool>> whereExpression, Expression<Func<TEntity, TResult>> selectcolumns, Expression<Func<TEntity, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc);

        #endregion 根据条件查询指定列返回记录

        #region 查询分页数据

        /// <summary>
        /// 查询分页数据
        /// </summary>
        /// <param name="search"></param>`
        /// <returns></returns>
        PageResponse<TEntityOutput> GetPageList(TEntitySearch search);

        /// <summary>
        /// 查询分页数据
        /// </summary>
        /// <param name="search"></param>
        /// <returns></returns>
        Task<PageResponse<TEntityOutput>> GetPageListAsync(TEntitySearch search);

        #endregion 查询分页数据

        #region 查询一条数据

        /// <summary>
        /// 查询一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntityOutput GetSingle(TKey id);

        /// <summary>
        /// 查询一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntityOutput> GetSingleAsync(TKey id);

        #endregion 查询一条数据

        #region 根据表达式查询一条数据

        /// <summary>
        /// 根据表达式查询一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        TEntityOutput GetSingle(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 根据表达式查询一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<TEntityOutput> GetSingleAsync(Expression<Func<TEntity, bool>> whereExpression);

        #endregion 根据表达式查询一条数据

        #region 根据主键判断数据是否存在

        /// <summary>
        /// 根据主键判断数据是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        bool IsAny(TKey id);

        /// <summary>
        /// 根据主键判断数据是否存在
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<bool> IsAnyAsync(TKey id);

        #endregion 根据主键判断数据是否存在

        #region 根据表达式判断数据是否存在

        /// <summary>
        /// 根据表达式判断数据是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        bool IsAny(Expression<Func<TEntity, bool>> whereExpression);

        /// <summary>
        /// 根据表达式判断数据是否存在
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        Task<bool> IsAnyAsync(Expression<Func<TEntity, bool>> whereExpression);

        #endregion 根据表达式判断数据是否存在

        #region 新增一条数据

        /// <summary>
        /// 新增一条数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        TEntityOutput Insert(TEntityInput input);

        /// <summary>
        /// 新增一条数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<TEntityOutput> InsertAsync(TEntityInput input);

        #endregion 新增一条数据

        #region 更新一条数据

        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        TEntityOutput Update(TEntityInput input);

        /// <summary>
        /// 更新一条数据
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        Task<TEntityOutput> UpdateAsync(TEntityInput input);

        #endregion 更新一条数据

        #region 根据条件更新指定列

        /// <summary>
        /// 根据条件更新指定列
        /// </summary>
        /// <param name="input"></param>
        /// <param name="updatecolumns"></param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        TEntityOutput UpdateColumns(TEntityInput input, Expression<Func<TEntity, object>> updatecolumns, Expression<Func<TEntity, bool>> whereExpression = null);

        /// <summary>
        /// 根据条件更新指定列
        /// </summary>
        /// <param name="input"></param>
        /// <param name="updatecolumns"></param>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        Task<TEntityOutput> UpdateColumnsAsync(TEntityInput input, Expression<Func<TEntity, object>> updatecolumns, Expression<Func<TEntity, bool>> whereExpression = null);

        #endregion 根据条件更新指定列

        #region 删除一条数据

        /// <summary>
        /// 删除一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isFake">是否逻辑删除</param>
        /// <returns></returns>
        bool Delete(TKey id, bool isFake = true);

        /// <summary>
        /// 删除一条数据
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isFake">是否逻辑删除</param>
        /// <returns></returns>
        Task<bool> DeleteAsync(TKey id, bool isFake = true);

        #endregion 删除一条数据

        #region 根据表达式删除数据

        /// <summary>
        /// 根据表达式删除数据
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="isFake">是否逻辑删除</param>
        /// <returns></returns>
        bool Delete(Expression<Func<TEntity, bool>> whereExpression, bool isFake = true);

        /// <summary>
        /// 根据表达式删除数据
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="isFake">是否逻辑删除</param>
        /// <returns></returns>
        Task<bool> DeleteAsync(Expression<Func<TEntity, bool>> whereExpression, bool isFake = true);

        #endregion 根据表达式删除数据

        #region 批量删除

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isFake">是否逻辑删除</param>
        /// <returns></returns>
        bool Delete(List<TKey> id, bool isFake = true);

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isFake">是否逻辑删除</param>
        /// <returns></returns>
        Task<bool> DeleteAsync(List<TKey> id, bool isFake = true);

        #endregion 批量删除

        #region 获取实体

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="input"></param>
        /// <param name="keyarray"></param>
        /// <param name="isadd"></param>
        /// <returns></returns>
        TEntity GetEntity(TEntityInput input, string[] keyarray = null, bool isadd = true);

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <param name="input"></param>
        /// <param name="keyarray"></param>
        /// <param name="isadd"></param>
        /// <returns></returns>
        Task<TEntity> GetEntityAsync(TEntityInput input, string[] keyarray = null, bool isadd = true);

        #endregion 获取实体

        #region  执行主函数存储过程

        /// <summary>
        /// 汤文
        /// 2022/03/20
        /// </summary>
        /// <param name="actionName">动作名</param>
        /// <param name="para">键</param>
        /// <param name="values">值</param>
        /// <param name="returnValue">返回值</param>
        /// <returns></returns>
        public void TransferStoredProc(string actionName, string para, string values, out string returnValue);
        #endregion

        /// <summary>
        /// 根据查询模型获取条件
        /// </summary>
        /// <param name="search"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        List<IConditionalModel> GetConditionals(TEntitySearch search, string prefix = "");
    }
}